﻿using MediatR;
using MES.Server.API.Application.Command.Weather;
using MES.Server.API.Dto.Weather;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using ReturnValue;
using System.Text.Json;
using System.Linq;

namespace MES.Server.API.Application.Handler.Weather
{
    /// <summary>
    /// 获取高德天气信息处理器
    /// </summary>
    public class GetGaoDeWeatherHander : IRequestHandler<GetGaoDeWeatherCommand, ApiResult<GaoDeWeatherOutPut>>
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _configuration;
        private readonly ILogger<GetGaoDeWeatherHander> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="httpClientFactory">HTTP客户端工厂</param>
        /// <param name="configuration">配置</param>
        /// <param name="logger">日志记录器</param>
        public GetGaoDeWeatherHander(
            IHttpClientFactory httpClientFactory,
            IConfiguration configuration,
            ILogger<GetGaoDeWeatherHander> logger)
        {
            _httpClient = httpClientFactory.CreateClient("WeatherApi");
            _configuration = configuration;
            _logger = logger;
        }

        /// <summary>
        /// 处理获取高德天气信息的请求
        /// </summary>
        /// <param name="request">请求命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>包含高德天气信息的API结果</returns>
        public async Task<ApiResult<GaoDeWeatherOutPut>> Handle(GetGaoDeWeatherCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<GaoDeWeatherOutPut>();

            try
            {
                // 1. 验证输入参数
                if (string.IsNullOrWhiteSpace(request.City))
                {
                    result.Code = ReturnValue.StatusCode.Fail;
                    result.Message = "城市编码不能为空";
                    return result;
                }

                // 2. 获取高德天气API配置
                var apiKey = _configuration["GaoDeWeather:ApiKey"];
                if (string.IsNullOrWhiteSpace(apiKey))
                {
                    result.Code = ReturnValue.StatusCode.Fail;
                    result.Message = "高德天气API密钥未配置";
                    return result;
                }

                // 3. 构建API请求URL
                var apiUrl = BuildApiUrl(apiKey, request.City, request.Extensions, request.Output);

                _logger.LogInformation("正在调用高德天气API，城市编码：{City}，URL：{Url}", request.City, apiUrl);

                // 4. 调用高德天气API
                var response = await _httpClient.GetAsync(apiUrl, cancellationToken);
                
                if (!response.IsSuccessStatusCode)
                {
                    result.Code = ReturnValue.StatusCode.Fail;
                    result.Message = $"调用高德天气API失败，状态码：{response.StatusCode}";
                    return result;
                }

                var jsonContent = await response.Content.ReadAsStringAsync(cancellationToken);
                _logger.LogInformation("高德天气API响应：{Response}", jsonContent);

                // 5. 解析API响应
                var weatherResponse = JsonSerializer.Deserialize<GaoDeWeatherApiResponse>(jsonContent, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                if (weatherResponse == null)
                {
                    result.Code = ReturnValue.StatusCode.Fail;
                    result.Message = "解析高德天气API响应失败";
                    return result;
                }

                // 6. 检查API返回状态
                if (weatherResponse.Status != "1")
                {
                    result.Code = ReturnValue.StatusCode.Fail;
                    result.Message = $"高德天气API返回错误：{weatherResponse.Info}";
                    return result;
                }

                // 7. 转换为输出DTO
                var output = ConvertToOutputDto(weatherResponse, request.Extensions);

                result.Code = ReturnValue.StatusCode.Success;
                result.Message = "获取高德天气信息成功";
                result.Data = output;

                return result;
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "调用高德天气API时发生网络错误，城市编码：{City}", request.City);
                result.Code = ReturnValue.StatusCode.Fail;
                result.Message = $"网络请求失败：{ex.Message}";
                return result;
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "解析高德天气API响应时发生JSON错误，城市编码：{City}", request.City);
                result.Code = ReturnValue.StatusCode.Fail;
                result.Message = $"解析响应数据失败：{ex.Message}";
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取高德天气信息时发生未知错误，城市编码：{City}", request.City);
                result.Code = ReturnValue.StatusCode.Fail;
                result.Message = $"获取天气信息失败：{ex.Message}";
                return result;
            }
        }

        /// <summary>
        /// 构建高德天气API请求URL
        /// </summary>
        /// <param name="apiKey">API密钥</param>
        /// <param name="city">城市编码</param>
        /// <param name="extensions">气象类型</param>
        /// <param name="output">返回格式</param>
        /// <returns>完整的API请求URL</returns>
        private string BuildApiUrl(string apiKey, string city, string extensions, string output)
        {
            var baseUrl = "https://restapi.amap.com/v3/weather/weatherInfo";
            var parameters = new List<string>
            {
                $"key={Uri.EscapeDataString(apiKey)}",
                $"city={Uri.EscapeDataString(city)}",
                $"extensions={Uri.EscapeDataString(extensions)}",
                $"output={Uri.EscapeDataString(output)}"
            };

            return $"{baseUrl}?{string.Join("&", parameters)}";
        }

        /// <summary>
        /// 将API响应转换为输出DTO
        /// </summary>
        /// <param name="apiResponse">API响应</param>
        /// <param name="extensions">气象类型</param>
        /// <returns>输出DTO</returns>
        private GaoDeWeatherOutPut ConvertToOutputDto(GaoDeWeatherApiResponse apiResponse, string extensions)
        {
            var output = new GaoDeWeatherOutPut
            {
                Status = apiResponse.Status,
                Count = apiResponse.Count,
                Info = apiResponse.Info,
                Infocode = apiResponse.Infocode,
                DataSource = "高德天气"
            };

            // 根据extensions参数处理不同的响应结构
            if (extensions == "base" && apiResponse.Lives != null && apiResponse.Lives.Any())
            {
                // 处理实况天气数据
                foreach (var live in apiResponse.Lives)
                {
                    output.Lives.Add(new GaoDeWeatherLiveOutPut
                    {
                        Province = live.Province,
                        City = live.City,
                        Adcode = live.Adcode,
                        Weather = live.Weather,
                        Temperature = live.Temperature,
                        WindDirection = live.WindDirection,
                        WindPower = live.WindPower,
                        Humidity = live.Humidity,
                        ReportTime = live.ReportTime
                    });
                }
            }
            else if (extensions == "all" && apiResponse.Forecasts != null && apiResponse.Forecasts.Any())
            {
                // 处理预报天气数据（取第一个预报数据）
                var forecast = apiResponse.Forecasts.First();
                output.Forecast = new GaoDeWeatherForecastOutPut
                {
                    City = forecast.City,
                    Adcode = forecast.Adcode,
                    Province = forecast.Province,
                    ReportTime = forecast.ReportTime
                };

                // 转换预报数据
                if (forecast.Casts != null)
                {
                    foreach (var cast in forecast.Casts)
                    {
                        output.Forecast.Casts.Add(new GaoDeWeatherCastOutPut
                        {
                            Date = cast.Date,
                            Week = cast.Week,
                            DayWeather = cast.DayWeather,
                            NightWeather = cast.NightWeather,
                            DayTemp = cast.DayTemp,
                            NightTemp = cast.NightTemp,
                            DayWind = cast.DayWind,
                            NightWind = cast.NightWind,
                            DayPower = cast.DayPower,
                            NightPower = cast.NightPower
                        });
                    }
                }
            }

            return output;
        }

        /// <summary>
        /// 解析日期时间字符串
        /// </summary>
        /// <param name="dateTimeString">日期时间字符串</param>
        /// <returns>解析后的日期时间，解析失败返回null</returns>
        private DateTime? ParseDateTime(string dateTimeString)
        {
            if (string.IsNullOrWhiteSpace(dateTimeString))
                return null;

            if (DateTime.TryParse(dateTimeString, out var result))
                return result;

            return null;
        }
    }

    /// <summary>
    /// 高德天气API响应模型
    /// </summary>
    public class GaoDeWeatherApiResponse
    {
        /// <summary>
        /// 状态码（0:失败, 1:成功）
        /// </summary>
        public string Status { get; set; }

        /// <summary>
        /// 返回结果总数目
        /// </summary>
        public string Count { get; set; }

        /// <summary>
        /// 返回的状态信息
        /// </summary>
        public string Info { get; set; }

        /// <summary>
        /// 返回状态说明（10000代表正确）
        /// </summary>
        public string Infocode { get; set; }

        /// <summary>
        /// 实况天气数据信息（当extensions=base时）
        /// </summary>
        public List<GaoDeWeatherLiveApi> Lives { get; set; } = new List<GaoDeWeatherLiveApi>();

        /// <summary>
        /// 预报天气信息数据（当extensions=all时）
        /// </summary>
        public List<GaoDeWeatherForecastApi> Forecasts { get; set; } = new List<GaoDeWeatherForecastApi>();
    }

    /// <summary>
    /// 高德天气实况数据API响应
    /// </summary>
    public class GaoDeWeatherLiveApi
    {
        /// <summary>
        /// 省份名
        /// </summary>
        public string Province { get; set; }

        /// <summary>
        /// 城市名
        /// </summary>
        public string City { get; set; }

        /// <summary>
        /// 区域编码
        /// </summary>
        public string Adcode { get; set; }

        /// <summary>
        /// 天气现象（汉字描述）
        /// </summary>
        public string Weather { get; set; }

        /// <summary>
        /// 实时气温，单位：摄氏度
        /// </summary>
        public string Temperature { get; set; }

        /// <summary>
        /// 风向描述
        /// </summary>
        public string WindDirection { get; set; }

        /// <summary>
        /// 风力级别，单位：级
        /// </summary>
        public string WindPower { get; set; }

        /// <summary>
        /// 空气湿度
        /// </summary>
        public string Humidity { get; set; }

        /// <summary>
        /// 数据发布的时间
        /// </summary>
        public string ReportTime { get; set; }
    }

    /// <summary>
    /// 高德天气预报数据API响应
    /// </summary>
    public class GaoDeWeatherForecastApi
    {
        /// <summary>
        /// 城市名称
        /// </summary>
        public string City { get; set; }

        /// <summary>
        /// 城市编码
        /// </summary>
        public string Adcode { get; set; }

        /// <summary>
        /// 省份名称
        /// </summary>
        public string Province { get; set; }

        /// <summary>
        /// 预报发布时间
        /// </summary>
        public string ReportTime { get; set; }

        /// <summary>
        /// 预报数据列表
        /// </summary>
        public List<GaoDeWeatherCastApi> Casts { get; set; } = new List<GaoDeWeatherCastApi>();
    }

    /// <summary>
    /// 高德天气预报数据项
    /// </summary>
    public class GaoDeWeatherCastApi
    {
        /// <summary>
        /// 日期
        /// </summary>
        public string Date { get; set; }

        /// <summary>
        /// 星期几
        /// </summary>
        public string Week { get; set; }

        /// <summary>
        /// 白天天气现象
        /// </summary>
        public string DayWeather { get; set; }

        /// <summary>
        /// 晚上天气现象
        /// </summary>
        public string NightWeather { get; set; }

        /// <summary>
        /// 白天温度
        /// </summary>
        public string DayTemp { get; set; }

        /// <summary>
        /// 晚上温度
        /// </summary>
        public string NightTemp { get; set; }

        /// <summary>
        /// 白天风向
        /// </summary>
        public string DayWind { get; set; }

        /// <summary>
        /// 晚上风向
        /// </summary>
        public string NightWind { get; set; }

        /// <summary>
        /// 白天风力
        /// </summary>
        public string DayPower { get; set; }

        /// <summary>
        /// 晚上风力
        /// </summary>
        public string NightPower { get; set; }
    }
}
